<?php namespace nimo\common\csv;

use DateTime;
use nimo\common\csv\CsvConverter;
use nimo\common\csv\CsvValidator;

class TableConverter implements CsvConverter {

    protected $column_defs = array();
    protected $indexed = null;
    protected $validator = null;

    public function __construct($column_defs, $configs = array())
    {
        $this->indexed = isset($configs['indexed']) ? $configs['indexed'] : null;
        $this->initColumnDefs($column_defs);
    }

    protected function initColumnDefs($column_defs)
    {
        //column_defs -> array('index' => 0, 'column' =>'id', etc),

        // rearrange for auto, indexed columns
        $columns_auto = array();
        $columns_indexed = array();
        foreach ($column_defs as $column) {
            if (!isset($column['index'] )) {
                $column['index'] = -1;
            }
            if (!isset($column['out'])) {
                $column['out'] = 1;
            }
            if ($column['index'] >= 0) {
                $columns_indexed[] = $column;
            } else {
                $columns_auto[] = $column;
            }
        }

        // sort indexed columns
        usort($columns_indexed, function($a, $b) { return ($a['index'] > $b['index']);});

        // rebuild columns def
        $rebuild = array();
        foreach ($columns_indexed as $column) {
            while (count($rebuild) < $column['index']) {
                $auto = array_shift($columns_auto);
                if (!$auto) {
                    $auto = array('out' => 0);
                }
                $auto['index'] = count($rebuild);
                $rebuild[] = $auto;
            }
            $rebuild[] = $column;
        }
        //add remaing auto columns
        while ($auto = array_shift($columns_auto)) {
            $auto['index'] = count($rebuild);
            $rebuild[] = $auto;
        }
        $this->column_defs = $rebuild;
    }
    protected function check_source_indexed($fields)
    {
        $count = 0;
        foreach ($fields as $key=>$value) {
            if (is_integer($key)) {
                $count++;
            } else {
                $count--;                
            }
        }
        $this->indexed = ($count>0) ? true : false;
    }

    public function set_validator(CsvValidator $validator) {
        $this->validator=$validator;
    }

    public function convert($fields) {
        if (count($this->column_defs) < 1) {
            return $fields;
        }
        if ($this->indexed === null) {
            $this->check_source_indexed($fields);
        }
        $r = array();
        if ($this->indexed) {
            foreach ($this->column_defs as $index=>$column) {
                if ($column['out'] === 0) {
                    continue;
                }
                if (!isset($column['column']) ) {
                    continue;
                }
                $value = null;
                if (isset($column['convert'])) {
                    $value = $column['convert']($fields);
                } else if (isset($fields[$index])) {
                    $value = $fields[$index];
                }
                $r[$column['column']] = $value;
            }
            if ($this->validator && !$this->validator->validate($r)) {
                return null;
            }
        } else {
            foreach ($this->column_defs as $index => $column) {
                if ($column['out'] === 0) {
                    continue;
                }
                $value = '';
                if (isset($column['convert'])) {
                    $value = $column['convert']($fields);
                } else if (isset($column['column']) ) {
                    $value = $fields[$column['column']];
                }
                $r[$index] = $value;
            }
        }
        return $r;
    }
}
